use crate::common::rdius::ChatRedis;
use crate::common::utils::sql_utils::{message_list_to_insert_sql, messages_to_insert_sql};
use crate::service::model::chat_handler_model;
use crate::service::model::chat_handler_model::{Connection, Disconnect, WsRequest};
use crate::sql::chat::exesql;
use actix::*;
use actix_web::rt::time::Instant;
use actix_web_actors::ws;
use sqlx::{Pool, Postgres};
use std::collections::HashMap;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;
use std::time::Duration;

pub struct ChatServer {
    pub session: HashMap<usize, Recipient<chat_handler_model::Message>>,
    pub pool: Pool<Postgres>,
    pub visitor_count: Arc<AtomicUsize>,
    pub redis: ChatRedis,
}

impl ChatServer {
    pub fn new(
        pool: Pool<Postgres>,
        redis: ChatRedis,
        visitor_count: Arc<AtomicUsize>,
    ) -> ChatServer {
        let chat = ChatServer {
            session: HashMap::new(),
            pool,
            visitor_count,
            redis,
        };

        chat
    }

    pub fn send_message(&self, chat: usize, message: &str) {
        if let Some(addr) = self.session.get(&chat) {
            addr.do_send(chat_handler_model::Message(message.to_lowercase(), true));
        }
    }

    pub fn send_disconnect(&self, chat: usize) {
        if let Some(addr) = self.session.get(&chat) {
            addr.do_send(chat_handler_model::Message("close".to_lowercase(), false));
        }
    }
}

impl Actor for ChatServer {
    type Context = Context<Self>;

    fn started(&mut self, ctx: &mut Self::Context) {
        ctx.run_interval(Duration::from_secs(30), |act, ctx| {
            //计数器缓存入库
            futures::executor::block_on(async {
                //message入库
                let mut messages = Vec::new();
                for x in act.redis.message.values() {
                    messages.extend(x);
                }
                if messages.len() > 0 {
                    let message_sql = messages_to_insert_sql(messages);
                    act.redis.message.clear();
                    exesql(&act.pool, &*message_sql).await;
                }
                //message_list插入数据库
                let mut message_list = Vec::new();
                for x in act.redis.message_list.values() {
                    message_list.extend(x.values());
                }
                if message_list.len() > 0 {
                    let message_list_sql = message_list_to_insert_sql(message_list);
                    act.redis.message_list.clear();
                    let _ = exesql(&act.pool, &*message_list_sql).await;
                }
            });
        });
    }
}
